// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.

namespace SixLabors.ImageSharp.Metadata.Profiles.Exif;

internal static partial class ExifValues
{
    public static ExifValue? Create(ExifTagValue tag) => (ExifValue?)CreateValue(tag);

    public static ExifValue? Create(ExifTag tag) => (ExifValue?)CreateValue((ExifTagValue)(ushort)tag);

    public static ExifValue? Create(ExifTagValue tag, ExifDataType dataType, ulong numberOfComponents) => Create(tag, dataType, numberOfComponents != 1);

    public static ExifValue? Create(ExifTagValue tag, ExifDataType dataType, bool isArray)
    {
        switch (dataType)
        {
            case ExifDataType.Byte:
                return isArray ? new ExifByteArray(tag, dataType) : new ExifByte(tag, dataType);
            case ExifDataType.DoubleFloat:
                return isArray ? new ExifDoubleArray(tag) : new ExifDouble(tag);
            case ExifDataType.SingleFloat:
                return isArray ? new ExifFloatArray(tag) : new ExifFloat(tag);
            case ExifDataType.Long:
                return isArray ? new ExifLongArray(tag) : new ExifLong(tag);
            case ExifDataType.Long8:
                return isArray ? new ExifLong8Array(tag) : new ExifLong8(tag);
            case ExifDataType.Rational:
                return isArray ? new ExifRationalArray(tag) : new ExifRational(tag);
            case ExifDataType.Short:
                return isArray ? new ExifShortArray(tag) : new ExifShort(tag);
            case ExifDataType.SignedByte:
                return isArray ? new ExifSignedByteArray(tag) : new ExifSignedByte(tag);
            case ExifDataType.SignedLong:
                return isArray ? new ExifSignedLongArray(tag) : new ExifSignedLong(tag);
            case ExifDataType.SignedLong8:
                return isArray ? new ExifSignedLong8Array(tag) : new ExifSignedLong8(tag);
            case ExifDataType.SignedRational:
                return isArray ? new ExifSignedRationalArray(tag) : new ExifSignedRational(tag);
            case ExifDataType.SignedShort:
                return isArray ? new ExifSignedShortArray(tag) : new ExifSignedShort(tag);
            case ExifDataType.Ascii:
                return new ExifString(tag);
            case ExifDataType.Undefined:
                return isArray ? new ExifByteArray(tag, dataType) : new ExifByte(tag, dataType);
            default:
                return null;
        }
    }

    private static object? CreateValue(ExifTagValue tag)
    {
        switch (tag)
        {
            case ExifTagValue.FaxProfile:
                return new ExifByte(ExifTag.FaxProfile, ExifDataType.Byte);
            case ExifTagValue.ModeNumber:
                return new ExifByte(ExifTag.ModeNumber, ExifDataType.Byte);
            case ExifTagValue.GPSAltitudeRef:
                return new ExifByte(ExifTag.GPSAltitudeRef, ExifDataType.Byte);

            case ExifTagValue.ClipPath:
                return new ExifByteArray(ExifTag.ClipPath, ExifDataType.Byte);
            case ExifTagValue.VersionYear:
                return new ExifByteArray(ExifTag.VersionYear, ExifDataType.Byte);
            case ExifTagValue.XMP:
                return new ExifByteArray(ExifTag.XMP, ExifDataType.Byte);
            case ExifTagValue.CFAPattern2:
                return new ExifByteArray(ExifTag.CFAPattern2, ExifDataType.Byte);
            case ExifTagValue.TIFFEPStandardID:
                return new ExifByteArray(ExifTag.TIFFEPStandardID, ExifDataType.Byte);
            case ExifTagValue.GPSVersionID:
                return new ExifByteArray(ExifTag.GPSVersionID, ExifDataType.Byte);

            case ExifTagValue.PixelScale:
                return new ExifDoubleArray(ExifTag.PixelScale);
            case ExifTagValue.IntergraphMatrix:
                return new ExifDoubleArray(ExifTag.IntergraphMatrix);
            case ExifTagValue.ModelTiePoint:
                return new ExifDoubleArray(ExifTag.ModelTiePoint);
            case ExifTagValue.ModelTransform:
                return new ExifDoubleArray(ExifTag.ModelTransform);

            case ExifTagValue.SubfileType:
                return new ExifLong(ExifTag.SubfileType);
            case ExifTagValue.SubIFDOffset:
                return new ExifLong(ExifTag.SubIFDOffset);
            case ExifTagValue.GPSIFDOffset:
                return new ExifLong(ExifTag.GPSIFDOffset);
            case ExifTagValue.T4Options:
                return new ExifLong(ExifTag.T4Options);
            case ExifTagValue.T6Options:
                return new ExifLong(ExifTag.T6Options);
            case ExifTagValue.XClipPathUnits:
                return new ExifLong(ExifTag.XClipPathUnits);
            case ExifTagValue.YClipPathUnits:
                return new ExifLong(ExifTag.YClipPathUnits);
            case ExifTagValue.ProfileType:
                return new ExifLong(ExifTag.ProfileType);
            case ExifTagValue.CodingMethods:
                return new ExifLong(ExifTag.CodingMethods);
            case ExifTagValue.T82ptions:
                return new ExifLong(ExifTag.T82ptions);
            case ExifTagValue.JPEGInterchangeFormat:
                return new ExifLong(ExifTag.JPEGInterchangeFormat);
            case ExifTagValue.JPEGInterchangeFormatLength:
                return new ExifLong(ExifTag.JPEGInterchangeFormatLength);
            case ExifTagValue.MDFileTag:
                return new ExifLong(ExifTag.MDFileTag);
            case ExifTagValue.StandardOutputSensitivity:
                return new ExifLong(ExifTag.StandardOutputSensitivity);
            case ExifTagValue.RecommendedExposureIndex:
                return new ExifLong(ExifTag.RecommendedExposureIndex);
            case ExifTagValue.ISOSpeed:
                return new ExifLong(ExifTag.ISOSpeed);
            case ExifTagValue.ISOSpeedLatitudeyyy:
                return new ExifLong(ExifTag.ISOSpeedLatitudeyyy);
            case ExifTagValue.ISOSpeedLatitudezzz:
                return new ExifLong(ExifTag.ISOSpeedLatitudezzz);
            case ExifTagValue.FaxRecvParams:
                return new ExifLong(ExifTag.FaxRecvParams);
            case ExifTagValue.FaxRecvTime:
                return new ExifLong(ExifTag.FaxRecvTime);
            case ExifTagValue.ImageNumber:
                return new ExifLong(ExifTag.ImageNumber);

            case ExifTagValue.FreeOffsets:
                return new ExifLongArray(ExifTag.FreeOffsets);
            case ExifTagValue.FreeByteCounts:
                return new ExifLongArray(ExifTag.FreeByteCounts);
            case ExifTagValue.ColorResponseUnit:
                return new ExifLongArray(ExifTag.ColorResponseUnit);
            case ExifTagValue.SMinSampleValue:
                return new ExifLongArray(ExifTag.SMinSampleValue);
            case ExifTagValue.SMaxSampleValue:
                return new ExifLongArray(ExifTag.SMaxSampleValue);
            case ExifTagValue.JPEGQTables:
                return new ExifLongArray(ExifTag.JPEGQTables);
            case ExifTagValue.JPEGDCTables:
                return new ExifLongArray(ExifTag.JPEGDCTables);
            case ExifTagValue.JPEGACTables:
                return new ExifLongArray(ExifTag.JPEGACTables);
            case ExifTagValue.StripRowCounts:
                return new ExifLongArray(ExifTag.StripRowCounts);
            case ExifTagValue.IntergraphRegisters:
                return new ExifLongArray(ExifTag.IntergraphRegisters);
            case ExifTagValue.SubIFDs:
                return new ExifLongArray(ExifTag.SubIFDs);

            case ExifTagValue.ImageWidth:
                return new ExifNumber(ExifTag.ImageWidth);
            case ExifTagValue.ImageLength:
                return new ExifNumber(ExifTag.ImageLength);
            case ExifTagValue.RowsPerStrip:
                return new ExifNumber(ExifTag.RowsPerStrip);
            case ExifTagValue.TileWidth:
                return new ExifNumber(ExifTag.TileWidth);
            case ExifTagValue.TileLength:
                return new ExifNumber(ExifTag.TileLength);
            case ExifTagValue.BadFaxLines:
                return new ExifNumber(ExifTag.BadFaxLines);
            case ExifTagValue.ConsecutiveBadFaxLines:
                return new ExifNumber(ExifTag.ConsecutiveBadFaxLines);
            case ExifTagValue.PixelXDimension:
                return new ExifNumber(ExifTag.PixelXDimension);
            case ExifTagValue.PixelYDimension:
                return new ExifNumber(ExifTag.PixelYDimension);

            case ExifTagValue.StripByteCounts:
                return new ExifNumberArray(ExifTag.StripByteCounts);
            case ExifTagValue.StripOffsets:
                return new ExifNumberArray(ExifTag.StripOffsets);
            case ExifTagValue.TileByteCounts:
                return new ExifNumberArray(ExifTag.TileByteCounts);
            case ExifTagValue.TileOffsets:
                return new ExifNumberArray(ExifTag.TileOffsets);
            case ExifTagValue.ImageLayer:
                return new ExifNumberArray(ExifTag.ImageLayer);

            case ExifTagValue.XPosition:
                return new ExifRational(ExifTag.XPosition);
            case ExifTagValue.YPosition:
                return new ExifRational(ExifTag.YPosition);
            case ExifTagValue.XResolution:
                return new ExifRational(ExifTag.XResolution);
            case ExifTagValue.YResolution:
                return new ExifRational(ExifTag.YResolution);
            case ExifTagValue.BatteryLevel:
                return new ExifRational(ExifTag.BatteryLevel);
            case ExifTagValue.ExposureTime:
                return new ExifRational(ExifTag.ExposureTime);
            case ExifTagValue.FNumber:
                return new ExifRational(ExifTag.FNumber);
            case ExifTagValue.MDScalePixel:
                return new ExifRational(ExifTag.MDScalePixel);
            case ExifTagValue.CompressedBitsPerPixel:
                return new ExifRational(ExifTag.CompressedBitsPerPixel);
            case ExifTagValue.ApertureValue:
                return new ExifRational(ExifTag.ApertureValue);
            case ExifTagValue.MaxApertureValue:
                return new ExifRational(ExifTag.MaxApertureValue);
            case ExifTagValue.SubjectDistance:
                return new ExifRational(ExifTag.SubjectDistance);
            case ExifTagValue.FocalLength:
                return new ExifRational(ExifTag.FocalLength);
            case ExifTagValue.FlashEnergy2:
                return new ExifRational(ExifTag.FlashEnergy2);
            case ExifTagValue.FocalPlaneXResolution2:
                return new ExifRational(ExifTag.FocalPlaneXResolution2);
            case ExifTagValue.FocalPlaneYResolution2:
                return new ExifRational(ExifTag.FocalPlaneYResolution2);
            case ExifTagValue.ExposureIndex2:
                return new ExifRational(ExifTag.ExposureIndex2);
            case ExifTagValue.Humidity:
                return new ExifRational(ExifTag.Humidity);
            case ExifTagValue.Pressure:
                return new ExifRational(ExifTag.Pressure);
            case ExifTagValue.Acceleration:
                return new ExifRational(ExifTag.Acceleration);
            case ExifTagValue.FlashEnergy:
                return new ExifRational(ExifTag.FlashEnergy);
            case ExifTagValue.FocalPlaneXResolution:
                return new ExifRational(ExifTag.FocalPlaneXResolution);
            case ExifTagValue.FocalPlaneYResolution:
                return new ExifRational(ExifTag.FocalPlaneYResolution);
            case ExifTagValue.ExposureIndex:
                return new ExifRational(ExifTag.ExposureIndex);
            case ExifTagValue.DigitalZoomRatio:
                return new ExifRational(ExifTag.DigitalZoomRatio);
            case ExifTagValue.GPSAltitude:
                return new ExifRational(ExifTag.GPSAltitude);
            case ExifTagValue.GPSDOP:
                return new ExifRational(ExifTag.GPSDOP);
            case ExifTagValue.GPSSpeed:
                return new ExifRational(ExifTag.GPSSpeed);
            case ExifTagValue.GPSTrack:
                return new ExifRational(ExifTag.GPSTrack);
            case ExifTagValue.GPSImgDirection:
                return new ExifRational(ExifTag.GPSImgDirection);
            case ExifTagValue.GPSDestBearing:
                return new ExifRational(ExifTag.GPSDestBearing);
            case ExifTagValue.GPSDestDistance:
                return new ExifRational(ExifTag.GPSDestDistance);
            case ExifTagValue.GPSHPositioningError:
                return new ExifRational(ExifTag.GPSHPositioningError);

            case ExifTagValue.WhitePoint:
                return new ExifRationalArray(ExifTag.WhitePoint);
            case ExifTagValue.PrimaryChromaticities:
                return new ExifRationalArray(ExifTag.PrimaryChromaticities);
            case ExifTagValue.YCbCrCoefficients:
                return new ExifRationalArray(ExifTag.YCbCrCoefficients);
            case ExifTagValue.ReferenceBlackWhite:
                return new ExifRationalArray(ExifTag.ReferenceBlackWhite);
            case ExifTagValue.GPSLatitude:
                return new ExifRationalArray(ExifTag.GPSLatitude);
            case ExifTagValue.GPSLongitude:
                return new ExifRationalArray(ExifTag.GPSLongitude);
            case ExifTagValue.GPSTimestamp:
                return new ExifRationalArray(ExifTag.GPSTimestamp);
            case ExifTagValue.GPSDestLatitude:
                return new ExifRationalArray(ExifTag.GPSDestLatitude);
            case ExifTagValue.GPSDestLongitude:
                return new ExifRationalArray(ExifTag.GPSDestLongitude);
            case ExifTagValue.LensSpecification:
                return new ExifRationalArray(ExifTag.LensSpecification);

            case ExifTagValue.OldSubfileType:
                return new ExifShort(ExifTag.OldSubfileType);
            case ExifTagValue.Compression:
                return new ExifShort(ExifTag.Compression);
            case ExifTagValue.PhotometricInterpretation:
                return new ExifShort(ExifTag.PhotometricInterpretation);
            case ExifTagValue.Thresholding:
                return new ExifShort(ExifTag.Thresholding);
            case ExifTagValue.CellWidth:
                return new ExifShort(ExifTag.CellWidth);
            case ExifTagValue.CellLength:
                return new ExifShort(ExifTag.CellLength);
            case ExifTagValue.FillOrder:
                return new ExifShort(ExifTag.FillOrder);
            case ExifTagValue.Orientation:
                return new ExifShort(ExifTag.Orientation);
            case ExifTagValue.SamplesPerPixel:
                return new ExifShort(ExifTag.SamplesPerPixel);
            case ExifTagValue.PlanarConfiguration:
                return new ExifShort(ExifTag.PlanarConfiguration);
            case ExifTagValue.Predictor:
                return new ExifShort(ExifTag.Predictor);
            case ExifTagValue.GrayResponseUnit:
                return new ExifShort(ExifTag.GrayResponseUnit);
            case ExifTagValue.ResolutionUnit:
                return new ExifShort(ExifTag.ResolutionUnit);
            case ExifTagValue.CleanFaxData:
                return new ExifShort(ExifTag.CleanFaxData);
            case ExifTagValue.InkSet:
                return new ExifShort(ExifTag.InkSet);
            case ExifTagValue.NumberOfInks:
                return new ExifShort(ExifTag.NumberOfInks);
            case ExifTagValue.DotRange:
                return new ExifShort(ExifTag.DotRange);
            case ExifTagValue.Indexed:
                return new ExifShort(ExifTag.Indexed);
            case ExifTagValue.OPIProxy:
                return new ExifShort(ExifTag.OPIProxy);
            case ExifTagValue.JPEGProc:
                return new ExifShort(ExifTag.JPEGProc);
            case ExifTagValue.JPEGRestartInterval:
                return new ExifShort(ExifTag.JPEGRestartInterval);
            case ExifTagValue.YCbCrPositioning:
                return new ExifShort(ExifTag.YCbCrPositioning);
            case ExifTagValue.Rating:
                return new ExifShort(ExifTag.Rating);
            case ExifTagValue.RatingPercent:
                return new ExifShort(ExifTag.RatingPercent);
            case ExifTagValue.ExposureProgram:
                return new ExifShort(ExifTag.ExposureProgram);
            case ExifTagValue.Interlace:
                return new ExifShort(ExifTag.Interlace);
            case ExifTagValue.SelfTimerMode:
                return new ExifShort(ExifTag.SelfTimerMode);
            case ExifTagValue.SensitivityType:
                return new ExifShort(ExifTag.SensitivityType);
            case ExifTagValue.MeteringMode:
                return new ExifShort(ExifTag.MeteringMode);
            case ExifTagValue.LightSource:
                return new ExifShort(ExifTag.LightSource);
            case ExifTagValue.FocalPlaneResolutionUnit2:
                return new ExifShort(ExifTag.FocalPlaneResolutionUnit2);
            case ExifTagValue.SensingMethod2:
                return new ExifShort(ExifTag.SensingMethod2);
            case ExifTagValue.Flash:
                return new ExifShort(ExifTag.Flash);
            case ExifTagValue.ColorSpace:
                return new ExifShort(ExifTag.ColorSpace);
            case ExifTagValue.FocalPlaneResolutionUnit:
                return new ExifShort(ExifTag.FocalPlaneResolutionUnit);
            case ExifTagValue.SensingMethod:
                return new ExifShort(ExifTag.SensingMethod);
            case ExifTagValue.CustomRendered:
                return new ExifShort(ExifTag.CustomRendered);
            case ExifTagValue.ExposureMode:
                return new ExifShort(ExifTag.ExposureMode);
            case ExifTagValue.WhiteBalance:
                return new ExifShort(ExifTag.WhiteBalance);
            case ExifTagValue.FocalLengthIn35mmFilm:
                return new ExifShort(ExifTag.FocalLengthIn35mmFilm);
            case ExifTagValue.SceneCaptureType:
                return new ExifShort(ExifTag.SceneCaptureType);
            case ExifTagValue.GainControl:
                return new ExifShort(ExifTag.GainControl);
            case ExifTagValue.Contrast:
                return new ExifShort(ExifTag.Contrast);
            case ExifTagValue.Saturation:
                return new ExifShort(ExifTag.Saturation);
            case ExifTagValue.Sharpness:
                return new ExifShort(ExifTag.Sharpness);
            case ExifTagValue.SubjectDistanceRange:
                return new ExifShort(ExifTag.SubjectDistanceRange);
            case ExifTagValue.GPSDifferential:
                return new ExifShort(ExifTag.GPSDifferential);

            case ExifTagValue.BitsPerSample:
                return new ExifShortArray(ExifTag.BitsPerSample);
            case ExifTagValue.MinSampleValue:
                return new ExifShortArray(ExifTag.MinSampleValue);
            case ExifTagValue.MaxSampleValue:
                return new ExifShortArray(ExifTag.MaxSampleValue);
            case ExifTagValue.GrayResponseCurve:
                return new ExifShortArray(ExifTag.GrayResponseCurve);
            case ExifTagValue.ColorMap:
                return new ExifShortArray(ExifTag.ColorMap);
            case ExifTagValue.ExtraSamples:
                return new ExifShortArray(ExifTag.ExtraSamples);
            case ExifTagValue.PageNumber:
                return new ExifShortArray(ExifTag.PageNumber);
            case ExifTagValue.TransferFunction:
                return new ExifShortArray(ExifTag.TransferFunction);
            case ExifTagValue.HalftoneHints:
                return new ExifShortArray(ExifTag.HalftoneHints);
            case ExifTagValue.SampleFormat:
                return new ExifShortArray(ExifTag.SampleFormat);
            case ExifTagValue.TransferRange:
                return new ExifShortArray(ExifTag.TransferRange);
            case ExifTagValue.DefaultImageColor:
                return new ExifShortArray(ExifTag.DefaultImageColor);
            case ExifTagValue.JPEGLosslessPredictors:
                return new ExifShortArray(ExifTag.JPEGLosslessPredictors);
            case ExifTagValue.JPEGPointTransforms:
                return new ExifShortArray(ExifTag.JPEGPointTransforms);
            case ExifTagValue.YCbCrSubsampling:
                return new ExifShortArray(ExifTag.YCbCrSubsampling);
            case ExifTagValue.CFARepeatPatternDim:
                return new ExifShortArray(ExifTag.CFARepeatPatternDim);
            case ExifTagValue.IntergraphPacketData:
                return new ExifShortArray(ExifTag.IntergraphPacketData);
            case ExifTagValue.ISOSpeedRatings:
                return new ExifShortArray(ExifTag.ISOSpeedRatings);
            case ExifTagValue.SubjectArea:
                return new ExifShortArray(ExifTag.SubjectArea);
            case ExifTagValue.SubjectLocation:
                return new ExifShortArray(ExifTag.SubjectLocation);

            case ExifTagValue.ShutterSpeedValue:
                return new ExifSignedRational(ExifTag.ShutterSpeedValue);
            case ExifTagValue.BrightnessValue:
                return new ExifSignedRational(ExifTag.BrightnessValue);
            case ExifTagValue.ExposureBiasValue:
                return new ExifSignedRational(ExifTag.ExposureBiasValue);
            case ExifTagValue.AmbientTemperature:
                return new ExifSignedRational(ExifTag.AmbientTemperature);
            case ExifTagValue.WaterDepth:
                return new ExifSignedRational(ExifTag.WaterDepth);
            case ExifTagValue.CameraElevationAngle:
                return new ExifSignedRational(ExifTag.CameraElevationAngle);

            case ExifTagValue.Decode:
                return new ExifSignedRationalArray(ExifTag.Decode);

            case ExifTagValue.TimeZoneOffset:
                return new ExifSignedShortArray(ExifTag.TimeZoneOffset);

            case ExifTagValue.ImageDescription:
                return new ExifString(ExifTag.ImageDescription);
            case ExifTagValue.Make:
                return new ExifString(ExifTag.Make);
            case ExifTagValue.Model:
                return new ExifString(ExifTag.Model);
            case ExifTagValue.Software:
                return new ExifString(ExifTag.Software);
            case ExifTagValue.DateTime:
                return new ExifString(ExifTag.DateTime);
            case ExifTagValue.Artist:
                return new ExifString(ExifTag.Artist);
            case ExifTagValue.HostComputer:
                return new ExifString(ExifTag.HostComputer);
            case ExifTagValue.Copyright:
                return new ExifString(ExifTag.Copyright);
            case ExifTagValue.DocumentName:
                return new ExifString(ExifTag.DocumentName);
            case ExifTagValue.PageName:
                return new ExifString(ExifTag.PageName);
            case ExifTagValue.InkNames:
                return new ExifString(ExifTag.InkNames);
            case ExifTagValue.TargetPrinter:
                return new ExifString(ExifTag.TargetPrinter);
            case ExifTagValue.ImageID:
                return new ExifString(ExifTag.ImageID);
            case ExifTagValue.MDLabName:
                return new ExifString(ExifTag.MDLabName);
            case ExifTagValue.MDSampleInfo:
                return new ExifString(ExifTag.MDSampleInfo);
            case ExifTagValue.MDPrepDate:
                return new ExifString(ExifTag.MDPrepDate);
            case ExifTagValue.MDPrepTime:
                return new ExifString(ExifTag.MDPrepTime);
            case ExifTagValue.MDFileUnits:
                return new ExifString(ExifTag.MDFileUnits);
            case ExifTagValue.SEMInfo:
                return new ExifString(ExifTag.SEMInfo);
            case ExifTagValue.SpectralSensitivity:
                return new ExifString(ExifTag.SpectralSensitivity);
            case ExifTagValue.DateTimeOriginal:
                return new ExifString(ExifTag.DateTimeOriginal);
            case ExifTagValue.DateTimeDigitized:
                return new ExifString(ExifTag.DateTimeDigitized);
            case ExifTagValue.SubsecTime:
                return new ExifString(ExifTag.SubsecTime);
            case ExifTagValue.SubsecTimeOriginal:
                return new ExifString(ExifTag.SubsecTimeOriginal);
            case ExifTagValue.SubsecTimeDigitized:
                return new ExifString(ExifTag.SubsecTimeDigitized);
            case ExifTagValue.RelatedSoundFile:
                return new ExifString(ExifTag.RelatedSoundFile);
            case ExifTagValue.FaxSubaddress:
                return new ExifString(ExifTag.FaxSubaddress);
            case ExifTagValue.OffsetTime:
                return new ExifString(ExifTag.OffsetTime);
            case ExifTagValue.OffsetTimeOriginal:
                return new ExifString(ExifTag.OffsetTimeOriginal);
            case ExifTagValue.OffsetTimeDigitized:
                return new ExifString(ExifTag.OffsetTimeDigitized);
            case ExifTagValue.SecurityClassification:
                return new ExifString(ExifTag.SecurityClassification);
            case ExifTagValue.ImageHistory:
                return new ExifString(ExifTag.ImageHistory);
            case ExifTagValue.ImageUniqueID:
                return new ExifString(ExifTag.ImageUniqueID);
            case ExifTagValue.OwnerName:
                return new ExifString(ExifTag.OwnerName);
            case ExifTagValue.SerialNumber:
                return new ExifString(ExifTag.SerialNumber);
            case ExifTagValue.LensMake:
                return new ExifString(ExifTag.LensMake);
            case ExifTagValue.LensModel:
                return new ExifString(ExifTag.LensModel);
            case ExifTagValue.LensSerialNumber:
                return new ExifString(ExifTag.LensSerialNumber);
            case ExifTagValue.GDALMetadata:
                return new ExifString(ExifTag.GDALMetadata);
            case ExifTagValue.GDALNoData:
                return new ExifString(ExifTag.GDALNoData);
            case ExifTagValue.GPSLatitudeRef:
                return new ExifString(ExifTag.GPSLatitudeRef);
            case ExifTagValue.GPSLongitudeRef:
                return new ExifString(ExifTag.GPSLongitudeRef);
            case ExifTagValue.GPSSatellites:
                return new ExifString(ExifTag.GPSSatellites);
            case ExifTagValue.GPSStatus:
                return new ExifString(ExifTag.GPSStatus);
            case ExifTagValue.GPSMeasureMode:
                return new ExifString(ExifTag.GPSMeasureMode);
            case ExifTagValue.GPSSpeedRef:
                return new ExifString(ExifTag.GPSSpeedRef);
            case ExifTagValue.GPSTrackRef:
                return new ExifString(ExifTag.GPSTrackRef);
            case ExifTagValue.GPSImgDirectionRef:
                return new ExifString(ExifTag.GPSImgDirectionRef);
            case ExifTagValue.GPSMapDatum:
                return new ExifString(ExifTag.GPSMapDatum);
            case ExifTagValue.GPSDestLatitudeRef:
                return new ExifString(ExifTag.GPSDestLatitudeRef);
            case ExifTagValue.GPSDestLongitudeRef:
                return new ExifString(ExifTag.GPSDestLongitudeRef);
            case ExifTagValue.GPSDestBearingRef:
                return new ExifString(ExifTag.GPSDestBearingRef);
            case ExifTagValue.GPSDestDistanceRef:
                return new ExifString(ExifTag.GPSDestDistanceRef);
            case ExifTagValue.GPSDateStamp:
                return new ExifString(ExifTag.GPSDateStamp);

            case ExifTagValue.FileSource:
                return new ExifByte(ExifTag.FileSource, ExifDataType.Undefined);
            case ExifTagValue.SceneType:
                return new ExifByte(ExifTag.SceneType, ExifDataType.Undefined);

            case ExifTagValue.JPEGTables:
                return new ExifByteArray(ExifTag.JPEGTables, ExifDataType.Undefined);
            case ExifTagValue.OECF:
                return new ExifByteArray(ExifTag.OECF, ExifDataType.Undefined);
            case ExifTagValue.ExifVersion:
                return new ExifByteArray(ExifTag.ExifVersion, ExifDataType.Undefined);
            case ExifTagValue.ComponentsConfiguration:
                return new ExifByteArray(ExifTag.ComponentsConfiguration, ExifDataType.Undefined);
            case ExifTagValue.MakerNote:
                return new ExifByteArray(ExifTag.MakerNote, ExifDataType.Undefined);
            case ExifTagValue.FlashpixVersion:
                return new ExifByteArray(ExifTag.FlashpixVersion, ExifDataType.Undefined);
            case ExifTagValue.SpatialFrequencyResponse:
                return new ExifByteArray(ExifTag.SpatialFrequencyResponse, ExifDataType.Undefined);
            case ExifTagValue.SpatialFrequencyResponse2:
                return new ExifByteArray(ExifTag.SpatialFrequencyResponse2, ExifDataType.Undefined);
            case ExifTagValue.Noise:
                return new ExifByteArray(ExifTag.Noise, ExifDataType.Undefined);
            case ExifTagValue.CFAPattern:
                return new ExifByteArray(ExifTag.CFAPattern, ExifDataType.Undefined);
            case ExifTagValue.DeviceSettingDescription:
                return new ExifByteArray(ExifTag.DeviceSettingDescription, ExifDataType.Undefined);
            case ExifTagValue.ImageSourceData:
                return new ExifByteArray(ExifTag.ImageSourceData, ExifDataType.Undefined);

            case ExifTagValue.XPTitle:
                return new ExifUcs2String(ExifTag.XPTitle);
            case ExifTagValue.XPComment:
                return new ExifUcs2String(ExifTag.XPComment);
            case ExifTagValue.XPAuthor:
                return new ExifUcs2String(ExifTag.XPAuthor);
            case ExifTagValue.XPKeywords:
                return new ExifUcs2String(ExifTag.XPKeywords);
            case ExifTagValue.XPSubject:
                return new ExifUcs2String(ExifTag.XPSubject);

            case ExifTagValue.UserComment:
                return new ExifEncodedString(ExifTag.UserComment);
            case ExifTagValue.GPSProcessingMethod:
                return new ExifEncodedString(ExifTag.GPSProcessingMethod);
            case ExifTagValue.GPSAreaInformation:
                return new ExifEncodedString(ExifTag.GPSAreaInformation);

            default:
                return null;
        }
    }
}
